/*
 * test.c
 *
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>

#define BLOCK_SIZE 512
#define EMPTY_BLOCK "EMPTY"

struct superblock {
	unsigned short isize;
	unsigned short fsize;
	unsigned short nfree;
	unsigned short free[100];
	unsigned short ninode;
	unsigned short inode[100];
	char flock;
	char ilock;
	char fmod;
	unsigned short time[2];
};

struct inode {
	unsigned short flags;
	char nlinks;
	char uid;
	char gid;
	char size0;
	unsigned short size1;
	unsigned short addr[8];
	unsigned short actime[2];
	unsigned short modtime[2];
};

struct directoryentry {
	unsigned short inodenumber;
	char filename[14];
};

unsigned long numberofinodesrem;
unsigned long numofdatablocksrem;
char currentpath[200]; /*This gives you the current working directory*/
unsigned short cparentinode; /*Current Parent inode #*/
unsigned short cinode; /*Current inode #*/
unsigned short iptr;
struct superblock superblock;
int fsfd;

int FileSystemInitialization(unsigned long totalfsblocks,
		unsigned long inodeblocks) {
	numofdatablocksrem = totalfsblocks - inodeblocks - 2; /*Blocks to store the contents of the file. Block 0 for Boot Strap and Block 1 for Superblock*/
	numberofinodesrem = inodeblocks * 16;
	struct inode inode;

	if (totalfsblocks < inodeblocks) {
		printf(
				"Arguements invalid; Total blocks cannot be less than inode blocks\n");
		exit(1);
	}
	/*To open the FS file*/
	if ((fsfd = open("v6fs", O_CREAT | O_RDWR | O_TRUNC, 0664)) < 0) {
		printf("ERROR in init: fsfd<0 fsfd value=%d\n", fsfd);
		exit(1);
	}

	/*Empty all the blocks of the File System*/
	EmptyTheBlocks(totalfsblocks);

	/*Create and Write to Super Block*/
	InitializeSuperBlock(inodeblocks);

	/*Create root directory*/
	CreateRootDirectory(inode, inodeblocks);

}

int EmptyTheBlocks(unsigned long totalfsblocks) {
	int i, byteswritten;
	char emptycontent[BLOCK_SIZE];

	for (i = 0; i < BLOCK_SIZE; i++) {
		emptycontent[i] = 0;
	}

	for (i = 0; i < totalfsblocks; i++) {
		byteswritten = write(fsfd, emptycontent, BLOCK_SIZE);
		if (byteswritten != BLOCK_SIZE)
			printf("ERROR: Unable to empty the FS blocks\n");
	}

	return 1;
}

int InitializeSuperBlock(unsigned long inodeblocks) {
	int i, rvalue;
	time_t presenttime;
	struct tm *currenttime;
	presenttime = time(0); /*This gives current time in secs*/
	currenttime = localtime(&presenttime); /*This converts secs into hrs and mins and returns a pointer to a 'struct tm'*/

	memset(&superblock, 0, sizeof(struct superblock));
	superblock.isize = inodeblocks;
	superblock.fsize = 0;
	superblock.nfree = 100;
	if (numofdatablocksrem >= 100) {
		for (i = 0; i < 100; i++) {
			superblock.free[i] = i; /*The first block is for the root directory. Block address is (2+inodeblocks)*BLOCK_SIZE*/
		}
	} else {
		for (i = 0; i < numofdatablocksrem; i++) {
			superblock.free[i] = i;
		}
		superblock.nfree = numofdatablocksrem;
	}
	superblock.ninode = 100;

	if ((inodeblocks * 16) > 100) {
		for (i = 0; i < 100; i++) {
			superblock.inode[i] = i; /*First inode (superblock.inode[0]) is for the root directory.*/
		}
	} else {
		for (i = 0; i < (inodeblocks * 16); i++) {
			superblock.inode[i] = i;
		}
		superblock.ninode = inodeblocks * 16;
	}
	superblock.flock = 0;
	superblock.ilock = 0;
	superblock.fmod = 0;
	superblock.time[0] = currenttime->tm_hour;
	superblock.time[1] = currenttime->tm_min;
	/*Writing to Superblock*/
	rvalue = lseek(fsfd, BLOCK_SIZE, SEEK_SET);
	if ((write(fsfd, &superblock, sizeof(struct superblock)))
			!= sizeof(struct superblock))
		printf("ERROR:Superblock not written\n");

	return 1;
}

int CreateRootDirectory(struct inode inode, unsigned long inodeblocks) {
	int i;
	int rvalue;
	char buffer[14];
	char eofindicator[4] = "EOF";
	struct directoryentry rdirectoryentry;
	time_t presenttime;
	struct tm *currenttime;
	presenttime = time(0); /*This gives current time in secs*/
	currenttime = localtime(&presenttime); /*This converts secs into hrs and mins and returns a pointer to a 'struct tm'*/

	memset(&inode, 0, sizeof(struct inode));
	inode.flags = 19876 * 2;
	inode.nlinks = 0;
	inode.uid = 1;
	inode.gid = 1;
	inode.size0 = 0; /*size0 and size1 gives the size of the file itself.*/
	inode.size1 = BLOCK_SIZE;
	/*Each directory has only 1 block of memory (I mean 512 Bytes). Therfore only 32 entries in 1 directory.*/

	inode.addr[0] = (2 + inodeblocks) * BLOCK_SIZE; /*First block after i-list is for the superblock.*/

	inode.actime[0] = currenttime->tm_hour;
	inode.actime[1] = currenttime->tm_min;
	inode.modtime[0] = currenttime->tm_hour;
	inode.modtime[1] = currenttime->tm_min;

	/*As you are allocating 1 inode to the root directory. This is the first inode in the i-list blocks.*/
	superblock.ninode--; /*The number free inodes IN THE SUPERBLOCK is reduced by 1*/
	numberofinodesrem--; /*The number of inodes now is (inodeblocks*16)-1*/
	numofdatablocksrem--; /*Total # of data blocks remaining now.*/

	/*Superblock modified; Hence update*/
	rvalue = lseek(fsfd, BLOCK_SIZE, SEEK_SET);
	if ((write(fsfd, &superblock, sizeof(struct superblock)))
			!= sizeof(struct superblock)) {
		printf("ERROR:Superblock not written\n");
		exit(1);
	}

	/*Write Inode info of the Root Directory.*/
	rvalue = lseek(fsfd, ((BLOCK_SIZE * 2) + (32 * superblock.inode[iptr])),
			SEEK_SET); /*This location contains the info abt the root directory*/
	iptr++; /*Points to the next free inode in the superblock. As it is
	 inc by 1 the next free inode would be
	 superblock.inode[iptr]=(2*BLOCK_SIZE)+(32*iptr)*/

	if ((write(fsfd, &inode, sizeof(struct inode))) != sizeof(struct inode)) {
		printf("ERROR:Root inode not written to the 1st block\n");
		exit(1);
	}

	rvalue = lseek(fsfd, inode.addr[0], SEEK_SET); /*Move to the first block right after the 'Inode List'*/
	rdirectoryentry.inodenumber = 0;

	/*Now create directory entries '.'-current directory and '..'-parent directory*/

	sprintf(buffer, ".");
	strcpy(rdirectoryentry.filename, buffer);
	if ((write(fsfd, &rdirectoryentry.inodenumber, sizeof(unsigned short)))
			!= sizeof(unsigned short)) {
		printf("ERROR:In Root Dir root inode number not written.\n");
		exit(1);
	}
	if ((write(fsfd, rdirectoryentry.filename, sizeof(rdirectoryentry.filename)))
			!= sizeof(rdirectoryentry.filename)) {
		printf("ERROR:Root filename not written.\n");
		exit(1);
	}
	sprintf(buffer, "..");
	strcpy(rdirectoryentry.filename, buffer);
	if ((write(fsfd, &rdirectoryentry.inodenumber, sizeof(unsigned short)))
			!= sizeof(unsigned short)) {
		printf("ERROR:In Root Dir parent inode number not written.\n");
		exit(1);
	}
	if ((write(fsfd, rdirectoryentry.filename, sizeof(rdirectoryentry.filename)))
			!= sizeof(rdirectoryentry.filename)) {
		printf("ERROR:Parent filename in Root Dir not written.\n");
		exit(1);
	}
	/*if ((write(fsfd, eofindicator, 4)) != 4) {
		printf("ERROR in initv6fs:EOF indicator not written.\n");
		exit(1);
	}*/
	/*Updating the current working directory, current inode # and parent inode # of the cwd*/

	strcpy(currentpath, "/"); /*Root Directory.*/
	unsigned short cparentinode = 0;
	unsigned short cinode = 0;

	close(fsfd);
	return 1;
}

////////////////////////////////////////////////////////
//////////// Create a new Directory ///////////////////
///////////////////////////////////////////////////////

////////////////////// helper functions ///////////////

//set the initial values for inode
struct inode initialize_inode(unsigned long inodeblocks){
	struct inode inode;
	memset(&inode, 0, sizeof(struct inode));
	time_t presenttime;
	struct tm *currenttime;
	presenttime = time(0); /*This gives current time in secs*/
	currenttime = localtime(&presenttime); /*This converts secs into hrs and mins and returns a pointer to a 'struct tm'*/


	inode.flags = 13180;//TODO Doesnt even evaluate to 16 bits in binary
	inode.nlinks = 0;
	inode.uid = 1;
	inode.gid = 1;
	inode.size0 = 0; /*size0 and size1 gives the size of the file itself.*/
	inode.size1 = BLOCK_SIZE;
	/*Each directory has only 1 block of memory (I mean 512 Bytes). Therfore only 32 entries in 1 directory.*/

	/*Check to see if there are any free data blocks left in the superblock.*/
	superblock.nfree--;
	if (superblock.free[superblock.nfree] == 0) {
		printf("ERROR:No more data blocks left\n");
		exit(1);
	} else{
		inode.addr[0] = (2 + inodeblocks + superblock.free[superblock.nfree])
				* BLOCK_SIZE; /*2 for BS and SB and 1 for SB data block.*/
	}
	inode.actime[0] = currenttime->tm_hour;
	inode.actime[1] = currenttime->tm_min;
	inode.modtime[0] = currenttime->tm_hour;
	inode.modtime[1] = currenttime->tm_min;
	return inode;
}

//update the filesystem inode and superblock
void update_sb_inode(int fsfd, struct inode inode){
	lseek(fsfd, ((BLOCK_SIZE * 2) + (32 * superblock.inode[iptr])),
				SEEK_SET); /*superblock.inode[iptr] contains the address of the next free inode*/

	if ((write(fsfd, &inode, sizeof(struct inode))) != sizeof(struct inode)) {
		printf("ERROR in mkdir:inode info not written\n");
		exit(1);
	}
	superblock.ninode--; /*The number free inodes IN THE SUPERBLOCK is reduced by 1*/
	numberofinodesrem--; /*The number of inodes now is (inodeblocks*16)-1*/
	numofdatablocksrem--; /*Total # of data blocks remaining now.*/

	/*Superblock modified. Write to Superblock.*/
	lseek(fsfd, BLOCK_SIZE, SEEK_SET);

	if ((write(fsfd, &superblock, sizeof(struct superblock)))
			!= sizeof(struct superblock)) {
		printf("ERROR in mkdir:Superblock not written\n");
		exit(1);
	}
}

//create a empty directory
void initialize_directory(int fsfd, struct inode inode){
	struct directoryentry rdirectoryentry;
	char buffer[14];
	int i;
	/*Create directory entries '.' and '..'*/
		lseek(fsfd, inode.addr[0], SEEK_SET);

		sprintf(buffer, ".");
		strcpy(rdirectoryentry.filename, buffer);
		rdirectoryentry.inodenumber = iptr;

		if ((write(fsfd, &rdirectoryentry.inodenumber, sizeof(unsigned short)))
				!= sizeof(unsigned short)) {
			printf("ERROR in mkdir:inode number not written.\n");
			exit(1);
		}
		if ((write(fsfd, rdirectoryentry.filename, sizeof(rdirectoryentry.filename)))
				!= sizeof(rdirectoryentry.filename)) {
			printf("ERROR in mkdir:filename not written.\n");
			exit(1);
		}

		sprintf(buffer, "..");
		strcpy(rdirectoryentry.filename, buffer);
		rdirectoryentry.inodenumber = cinode;//TODO Check

		if ((write(fsfd, &rdirectoryentry.inodenumber, sizeof(unsigned short)))
				!= sizeof(unsigned short)) {
			printf("ERROR in mkdir:inode number not written.\n");
			exit(1);
		}
		if ((write(fsfd, rdirectoryentry.filename, sizeof(rdirectoryentry.filename)))
				!= sizeof(rdirectoryentry.filename)) {
			printf("ERROR in mkdir:filename not written.\n");
			exit(1);
		}
		lseek(fsfd, 2, SEEK_CUR);
		for (i = 0; i < 30; ++i) {
			write(fsfd, EMPTY_BLOCK, 14);
			lseek(fsfd, 2, SEEK_CUR);
		}

}

//update the parent directory
void update_parent_dir(int fsfd, char* directoryname){
	struct directoryentry rdirectoryentry;
	int i;
	unsigned short position;

	char empty[14];
	lseek(fsfd, ((BLOCK_SIZE * 2) + (32 * cinode) + 8), SEEK_SET);//TODO check again
	/*You've reached the parent inode of this directory you created.'+8' actually moves to the address
	 part of the inode which contains the address of the data block of the parent directory.*/

	read(fsfd, &position, sizeof(unsigned short));
	/*position gives the address of the data block.*/

	position = position + 32; /*Move by extra 32 bytes to skip the parent and the current dir info.*/
	lseek(fsfd, position + 2, SEEK_SET);

	for (i = 0; i < 30; i++) /*i<30 coz you've already moved by 32 bytes.*/
	{
		read(fsfd, empty, 14);
		if (!strcmp(EMPTY_BLOCK,empty) || !strcmp("",empty))
			break;
		position = position + 16;
		lseek(fsfd, position, SEEK_SET);
	}

	lseek(fsfd, position, SEEK_SET); /*Goto that position where you need to make an entry.*/
	rdirectoryentry.inodenumber = iptr;
	//rdirectoryentry.filename=directoryname;

	if ((write(fsfd, &rdirectoryentry.inodenumber, sizeof(unsigned short)))
			!= sizeof(unsigned short)) {
		printf(
				"ERROR in mkdir:inode number of the directory created not written.\n");
		exit(1);
	}
	if ((write(fsfd, directoryname, sizeof(rdirectoryentry.filename)))
			!= sizeof(rdirectoryentry.filename)) {
		printf(
				"ERROR in mkdir:filename of the directory created not written.\n");
		exit(1);
	}
}
/////////////////////////////////////////////////////////////////

////////////////////// Mkdir Command ///////////////////////////

int Mkdir(unsigned long inodeblocks, char *directoryname){
	struct inode inode;


	/*To open the FS file*/
	if ((fsfd = open("v6fs", O_RDWR)) < 0) {
		printf("ERROR in mkdir: fsfd<0\n");
		exit(1);
	}

	/*Check if the inodes are available.*/
	if ((iptr == 100) && (superblock.ninode == 0)) /*If iptr goes to 100 fill your inode array in the SB.*/
	{
		printf("ERROR:The number of inodes in the superblock ");
		exit(1);
	}
	inode = initialize_inode(inodeblocks);
	/*Write the necessary parameters to the inode.*/
	update_sb_inode(fsfd, inode);

	initialize_directory(fsfd, inode);

	/*So, now you've created a new directory. Make an entry for this directory in it's parent directory.*/
	update_parent_dir(fsfd, directoryname);

	iptr++; /*Next available inode number is iptr.*/
	close(fsfd);

	return 1;
}

///////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////
////////////	CHANGE DIRECTORY COMMAND  /////////////
/////////////////////////////////////////////////////


//////////////// Helper functions ///////////////////

//used when user cd's to ..
void truncate_current_path() {
	int i;
	char temp[200];
	int parentroot = 0; //flag to indicate parent is root

	for (i = (sizeof currentpath) - 1; i > 0; i--) {
		if (currentpath[i] == '/') {
			strncpy(temp, currentpath, i);
			temp[i] = '\0';
			strcpy(currentpath, temp);
			break;
		}
		if (i == 1) {
			parentroot = 1;
		}
	}
	if (parentroot) {
		strcpy(currentpath, "/");
	}
}

//returns address of datablock of inode 
//NOTE : Might get complicated when files are involved
unsigned short read_dblock_addr(int fsfd, unsigned short inode) {
	unsigned short dblock;
	lseek(fsfd, ((BLOCK_SIZE * 2) + (32 * inode) + 8), SEEK_SET);
	read(fsfd, &dblock, 2);
	return dblock;
}

//ASSUMPTION : fsfd is at the head of datablock
//returns the parent inode value
unsigned short get_parent_inode(int fsfd) {
	unsigned short p_inode;
	lseek(fsfd, 16, SEEK_CUR);
	read(fsfd, &p_inode, 2);
	return p_inode;
}

//searches for an entry in a directory
//and returns its number in the list
int get_entry_num(int fsfd, char *fname) {
	int i;
	lseek(fsfd, 34, SEEK_CUR);
	char entry[14];
	for (i = 2; i < 32; i++) {
		read(fsfd, entry, 14);
		if (!strcmp(fname, entry)) {
			printf("DEBUG : i is %d\n", i);
			return i;
		}
		lseek(fsfd, 2, SEEK_CUR);
	}
	return 32;
}


//just for debug
void display_dir_contents(unsigned short in_no){
	int i;
	unsigned short in;
	char name[14];
	/*To open the FS file*/
		if ((fsfd = open("v6fs", O_RDWR)) < 0) {
			printf("ERROR in cd: fsfd<0\n");
			exit(1);
		}

		unsigned short db = read_dblock_addr(fsfd, in_no);
		lseek(fsfd, db, SEEK_SET);

		printf("Printing Contents of Dir\n");
		for (i = 0; i < 32; i++) {
			read(fsfd, &in,2);
			read(fsfd, name, 14);

			printf("%hu\t%s\n", in,name);
		}
}
/////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////// Cd command //////////////////////////////
int Cd(char *fname) {

	//Cd to the same directory
	if (!strcmp(fname, ".")) {
		return 1;
	}

	/*To open the FS file*/
	if ((fsfd = open("v6fs", O_RDWR)) < 0) {
		printf("ERROR in cd: fsfd<0\n");
		exit(1);
	}

	//Cd to the parent
	if (!strcmp(fname, "..")) {
		truncate_current_path();
		unsigned short dblock = read_dblock_addr(fsfd, cinode);
		lseek(fsfd, dblock, SEEK_SET);

		cinode = get_parent_inode(fsfd);
		dblock = read_dblock_addr(fsfd, cinode);
		lseek(fsfd, dblock, SEEK_SET);

		cparentinode = get_parent_inode(fsfd);

		printf("DEBUG : cinode, cpinode :: %hu, %hu \n", cinode, cparentinode);

		close(fsfd);
		return 1;
	}

	unsigned short dblock = read_dblock_addr(fsfd, cinode);
	lseek(fsfd, dblock, SEEK_SET);
	int entry_num = get_entry_num(fsfd, fname);
	printf("DEBUG : entry_num :: %d\n", entry_num);
	if (entry_num < 32) {
		lseek(fsfd, (dblock + (entry_num * 16)), SEEK_SET);
		cparentinode = cinode;
		read(fsfd, &cinode, 2);

		printf("DEBUG : cinode, cpinode :: %hu, %hu \n", cinode, cparentinode);

		/*Now, update your current working directory.*/
		if (strcmp(currentpath, "/")) {
			strcat(currentpath, "/");
		}
		strcat(currentpath, fname);

	} else {
		printf("Cd: %s: No such file or directory\n", fname);
	}

	display_dir_contents(cinode);

	close(fsfd);
	return 1;
}
///////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////
///////////// Remove Directory Command /////////////////
////////////////////////////////////////////////////////

/////////////// Helper Functions ///////////////////////

//updates the superblock
void update_sb_rm(int fsfd, unsigned short inode, unsigned short dblock) {
	unsigned short l_free[100];
	unsigned short l_nfree;
	unsigned short l_inode[100];
	unsigned short l_ninode;

	lseek(fsfd, BLOCK_SIZE + 4, SEEK_SET);
	read(fsfd, &l_nfree, 2);
	read(fsfd, l_free, 200);

	l_free[l_nfree] = dblock;
	l_nfree++;

	lseek(fsfd, BLOCK_SIZE + 4, SEEK_SET);
	write(fsfd, &l_nfree, 2);
	write(fsfd, l_free, 200);

	read(fsfd, &l_ninode, 2);
	read(fsfd, l_inode, 200);

	printf("inode to add :: %hu, current first free inode :: %hu\n", inode,
			l_inode[iptr]);
	iptr--;
	l_ninode++;
	l_inode[iptr] = inode;

	lseek(fsfd, BLOCK_SIZE + 206, SEEK_SET);
	write(fsfd, &l_ninode, 2);
	write(fsfd, l_inode, 200);

}

void update_inode_rm(int fsfd, unsigned short inode) {

	unsigned short reset = 0;

	lseek(fsfd, ((BLOCK_SIZE * 2) + (32 * inode)), SEEK_SET);
	write(fsfd, &reset, 2);
}

int isEmpty(int fsfd){
	int i;
	char fname[14];
	lseek(fsfd,34,SEEK_CUR);

	for (i = 2; i < 32; i++) {
		read(fsfd, fname, 14);
		if(strcmp(EMPTY_BLOCK, fname)){
			return 0;
		}
		/*if(strcmp("",fname)){
			return 0;
		}*/

		lseek(fsfd, 2, SEEK_CUR);
	}

	return 1;
}

//////////////////////////////////////////////////////////////////////////

//////////////////////////////// Rmdir Command ///////////////////////////
int Rmdir(char* dirname) {

	unsigned short del_inode;
	unsigned short del_dblock;

	//open file system
	if ((fsfd = open("v6fs", O_RDWR)) < 0) {
		printf("ERROR in cd: fsfd<0\n");
		exit(1);
	}

	//reach the datablock
	unsigned short dblock = read_dblock_addr(fsfd, cinode);
	lseek(fsfd, dblock, SEEK_SET);

	//search for the entry
	int entry_num = get_entry_num(fsfd, dirname);
	if (entry_num < 32) {
		lseek(fsfd, (dblock + (entry_num * 16)), SEEK_SET);
		read(fsfd, &del_inode, 2);
		del_dblock = read_dblock_addr(fsfd, del_inode);
		lseek(fsfd, del_dblock,SEEK_SET);

		if(!isEmpty(fsfd)){
			printf("Rmdir : %s : Directory not empty\n",dirname);
			return 1;
		}else{
			lseek(fsfd, (dblock + (entry_num * 16) + 2),SEEK_SET);
			write(fsfd, EMPTY_BLOCK, 14);

			printf("del_inode :: %hu\n", del_inode);
			del_dblock = read_dblock_addr(fsfd, del_inode);
			update_inode_rm(fsfd, del_inode);
			update_sb_rm(fsfd, del_inode, del_dblock);

			close(fsfd);
			return 1;
		}
	}

	printf("Rmdir: failed to remove '%s': No such file or directory\n", dirname);
	close(fsfd);
	return 1;
}

///////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
//////////////////////// Chmod Command /////////////////////////////////////
////////////////////////////////////////////////////////////////////////////

//////////////////////// helper functions //////////////////////////////////


//////////////////////// Chmod Command  /////////////////////////////////

int Chmod(unsigned short mode, char *fname) {

	unsigned short mod_inode;
	unsigned short prev_flag;
	unsigned short updated_flag;

	//open file system
	if ((fsfd = open("v6fs", O_RDWR)) < 0) {
		printf("ERROR in cd: fsfd<0\n");
		exit(1);
	}

	//reach the datablock
	unsigned short dblock = read_dblock_addr(fsfd, cinode);
	lseek(fsfd, dblock, SEEK_SET);

	//search for the entry
	int entry_num = get_entry_num(fsfd, fname);
	printf("DEBUG : entry_num :: %d\n", entry_num);
	if (entry_num < 32) {
		lseek(fsfd, (dblock + (entry_num * 16)), SEEK_SET);
		read(fsfd, &mod_inode, 2);

		lseek(fsfd, ((BLOCK_SIZE * 2) + (32 * mod_inode)), SEEK_SET);
		read(fsfd, &prev_flag, 2);
		updated_flag = prev_flag | mode;

		lseek(fsfd, ((BLOCK_SIZE * 2) + (32 * mod_inode)), SEEK_SET);
		write(fsfd, &updated_flag, 2);

		close(fsfd);
		return 1;
	}

	printf("Chmod: cannot access '%s': No such file or directory\n", fname);
	close(fsfd);
	return 1;

}
//Only for debugging
void check_flag_values() {

	unsigned short flag;

	//open file system
	if ((fsfd = open("v6fs", O_RDWR)) < 0) {
		printf("ERROR in cd: fsfd<0\n");
		exit(1);
	}

	lseek(fsfd, ((BLOCK_SIZE * 2) + (32)), SEEK_SET);
	read(fsfd, &flag, 2);
	printf("Inode 1 Flag value :: %hu\n", flag);
}

int main() {
	iptr = 0;
	int rvalue;
	char buffer[20];
	char commandarg[50];
	unsigned long arg1 = 0, arg2 = 0;
	int i = 0;

	printf("Please initialize the File System\n");

	scanf("%s", buffer);
	if (!strcmp(buffer, "init")) {
		scanf("%uld", &arg1);
		scanf("%uld", &arg2);
		rvalue = FileSystemInitialization(arg1, arg2);
		printf("$v6fs%s> ", currentpath);
		/*Once you initialize your FS you close your file descriptor.
		 Hence open it again while you try to execute commands.*/
	} else {
		printf("Please initialize the File System\n");
	}

	while (1) {
		scanf("%s", buffer);
		if (!strcmp(buffer, "Mkdir")) {
			scanf("%s", commandarg);
			rvalue = Mkdir(arg2, commandarg);
			printf("$v6fs%s> ", currentpath);
		} else if (!strcmp(buffer, "Cd")) {
			scanf("%s", commandarg);
			rvalue = Cd(commandarg);
			printf("$v6fs%s> ", currentpath);
		} else if (!strcmp(buffer, "quit")) {
			exit(1);
		} else if (!strcmp(buffer, "pwd")) {
			printf("%s\n", currentpath);
			printf("$v6fs%s> ", currentpath);
		} else if (!strcmp(buffer, "Rmdir")) {
			scanf("%s", commandarg);
			Rmdir(commandarg);
			printf("$v6fs%s> ", currentpath);
		} else if (!strcmp(buffer, "Chmod")) {//TODO Handle wrong inputs
			check_flag_values();

			unsigned int arg1;

			scanf("%o", &arg1);
			scanf("%s", commandarg);

			printf("%hu\n", (unsigned short) arg1);
			Chmod((unsigned short) arg1, commandarg);
			check_flag_values();
			printf("$v6fs%s> ", currentpath);
		} else {
			printf("%s : command not found\n", buffer);
			printf("$v6fs%s> ", currentpath);
			//exit(1);
		}
	}
}
